home *** CD-ROM | disk | FTP | other *** search
- /* $Revision Header *** Header built automatically - do not edit! ***********
- *
- * (C) Copyright 1991 by Torsten Jürgeleit
- *
- * Name .....: render.c
- * Created ..: Thursday 19-Dec-91 15:14:35
- * Revision .: 12
- *
- * Date Author Comment
- * ========= ==================== ====================
- * 14-Sep-92 Torsten Jürgeleit open_window(): new flag to prevent
- * adding of inner window offsets
- * 28-Jul-92 Torsten Jürgeleit save window pointer in RenderInfo
- * 28-Jul-92 Torsten Jürgeleit open_window(): now correct window
- * position if RENDER_INFO_FLAG_-
- * INNER_WINDOW set
- * 23-Jun-92 Torsten Jürgeleit close_window() now checks if
- * win->UserPort exists before trying
- * to reply all IntuiMessages
- * 22-Jun-92 Torsten Jürgeleit after modifying NewWindow struct
- * for inner window mode new window
- * dimension is scaled once again in
- * open_window()
- * 12-May-92 Torsten Jürgeleit text colors for clear_window()
- * 30-Apr-92 Torsten Jürgeleit raster for clear_window()
- * 26-Apr-92 Torsten Jürgeleit special algorithm to calc text 2
- * pen for screens with 1 or 2 planes
- * 22-Mar-92 Torsten Jürgeleit mungwall hit in create_avail_fonts
- * no CopyMem() instead of 2nd
- * AvailFonts() allowed
- * 18-Mar-92 Torsten Jürgeleit calc inner window dimension BEFORE
- * centering window in open_window()
- * 06-Jan-92 Torsten Jürgeleit add font support routines
- * 19-Dec-91 Torsten Jürgeleit Created this file!
- *
- ****************************************************************************
- *
- * Routines to get information needed to render ISUP objects and some
- * window support functions
- *
- * $Revision Header ********************************************************/
-
- /* Includes */
-
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <libraries/diskfont.h>
- #include <intuition/intuition.h>
- #ifdef AZTEC_C
- #include <functions.h> /* needed for Aztec C - prototypes and pragmas for all Amiga system functions */
- #endif
- #include <libraries/memwatch.h> /* header file for memory debug link library (Fish 240) - AFTER functions.h */
- #include "render.h"
-
- /* Defines */
-
- #define RED_SCALE 3 /* amount of RGB values to take in account the different visual impact of those colors */
- #define GREEN_SCALE 6
- #define BLUE_SCALE 2
-
- #define DEFAULT_AVAIL_FONTS_BUFFER_SIZE 1000
-
- /* Externals */
-
- IMPORT struct IntuitionBase *IntuitionBase;
-
- /* Statics */
-
- STATIC USHORT image_data_arrow_left[] = { /* bitmap data for left arrow image */
- 0x0780, 0x3e00, 0xf800, 0x3e00, 0x0780, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000
- };
- STATIC USHORT image_data_arrow_right[] = { /* bitmap data for right arrow image */
- 0xf000, 0x3e00, 0x0f80, 0x3e00, 0xf000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000
- };
- STATIC USHORT image_data_arrow_up[] = { /* bitmap data for up arrow image */
- 0x0800, 0x1c00, 0x3e00, 0x7700, 0xc180, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000
- };
- STATIC USHORT image_data_arrow_down[] = { /* bitmap data for down arrow image */
- 0xc180, 0x7700, 0x3e00, 0x1c00, 0x0800, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000
- };
- STATIC USHORT image_data_toggle_knob_unselected[] = { /* bitmap data for unselected toggle knob image */
- 0x1ffc, 0x0000, 0x7000, 0x0000, 0xc000, 0x0000, 0xc000, 0x0000,
- 0xc000, 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0x7000, 0x0000,
- 0x1000, 0x0000, /* Plane 0 */
- 0x0002, 0x0000, 0x0003, 0x8000, 0x0000, 0xc000, 0x0000, 0xc000,
- 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0xc000, 0x0003, 0x8000,
- 0x0ffe, 0x0000 /* Plane 1 */
- };
- STATIC USHORT image_data_toggle_knob_selected[] = { /* bitmap data for selected toggle knob image */
- 0x0002, 0x0000, 0x0003, 0x8000, 0x03f0, 0xc000, 0x0ffc, 0xc000,
- 0x0ffc, 0xc000, 0x0ffc, 0xc000, 0x03f0, 0xc000, 0x0003, 0x8000,
- 0x0ffe, 0x0000, /* Plane 0 */
- 0x1ffc, 0x0000, 0x7000, 0x0000, 0xc3f0, 0x0000, 0xcffc, 0x0000,
- 0xcffc, 0x0000, 0xcffc, 0x0000, 0xc3f0, 0x0000, 0x7000, 0x0000,
- 0x1000, 0x0000 /* Plane 1 */
- };
- STATIC USHORT image_data_toggle_check_selected[] = { /* bitmap data for selected toggle checkmark image */
- 0x0038, 0x0060, 0x00c0, 0xe180, 0x7300, 0x3e00, 0x1c00
- };
- STATIC USHORT image_data_cycle[] = { /* bitmap data for cycle image */
- 0x7f01, 0xc181, 0xc181, 0xc7e1, 0xc3c1, 0xc181, 0xc001, 0xc181,
- 0x7f01, /* Plane 0 */
- 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
- 0x0002 /* Plane 1 */
- };
- STATIC USHORT image_data_count_left[] = { /* bitmap data for left count image */
- 0x0700, 0x3f00, 0xff00, 0x3f00, 0x0700
- };
- STATIC USHORT image_data_count_right[] = { /* bitmap data for right count image */
- 0xe000, 0xfc00, 0xff00, 0xfc00, 0xe000
- };
- STATIC struct Image images[] = {
- { /* left arrow */
- 0, 0, IMAGE_ARROW_WIDTH, IMAGE_ARROW_HEIGHT, IMAGE_ARROW_DEPTH,
- &image_data_arrow_left[0], 0, 0, NULL
- }, { /* right arrow */
- 0, 0, IMAGE_ARROW_WIDTH, IMAGE_ARROW_HEIGHT, IMAGE_ARROW_DEPTH,
- &image_data_arrow_right[0], 0, 0, NULL
- }, { /* up arrow */
- 0, 0, IMAGE_ARROW_WIDTH, IMAGE_ARROW_HEIGHT, IMAGE_ARROW_DEPTH,
- &image_data_arrow_up[0], 0, 0, NULL
- }, { /* down arrow */
- 0, 0, IMAGE_ARROW_WIDTH, IMAGE_ARROW_HEIGHT, IMAGE_ARROW_DEPTH,
- &image_data_arrow_down[0], 0, 0, NULL
- }, { /* toggle select knob unselected */
- 0, 0, IMAGE_KNOB_WIDTH, IMAGE_KNOB_HEIGHT, IMAGE_KNOB_DEPTH,
- &image_data_toggle_knob_unselected[0], 0, 0, NULL
- }, { /* toggle select knob selected */
- 0, 0, IMAGE_KNOB_WIDTH, IMAGE_KNOB_HEIGHT, IMAGE_KNOB_DEPTH,
- &image_data_toggle_knob_selected[0], 0, 0, NULL
- }, { /* toggle select check unselected */
- IMAGE_HORIZ_OFFSET, IMAGE_VERT_OFFSET, IMAGE_CHECK_WIDTH,
- IMAGE_CHECK_HEIGHT, 0, NULL, 0, 0, NULL
- }, { /* toggle select check selected */
- IMAGE_HORIZ_OFFSET, IMAGE_VERT_OFFSET, IMAGE_CHECK_WIDTH,
- IMAGE_CHECK_HEIGHT, IMAGE_CHECK_DEPTH,
- &image_data_toggle_check_selected[0], 0, 0, NULL
- }, { /* cycle */
- 0, 0, IMAGE_CYCLE_WIDTH, IMAGE_CYCLE_HEIGHT, IMAGE_CYCLE_DEPTH,
- &image_data_cycle[0], 0, 0, NULL
- }, { /* left count */
- 0, 0, IMAGE_COUNT_WIDTH, IMAGE_COUNT_HEIGHT, IMAGE_COUNT_DEPTH,
- &image_data_count_left[0], 0, 0, NULL
- }, { /* right count */
- 0, 0, IMAGE_COUNT_WIDTH, IMAGE_COUNT_HEIGHT, IMAGE_COUNT_DEPTH,
- &image_data_count_right[0], 0, 0, NULL
- }
- };
- STATIC struct TextAttr topaz80_attr = { (STRPTR)"topaz.font", TOPAZ_EIGHTY,
- FS_NORMAL, FPF_ROMFONT };
- /* Static prototypes */
-
- SHORT calc_color_level(SHORT color);
- VOID init_render_info_images(struct RenderInfo *ri);
- UBYTE get_image_pixel_color(struct Image *image, USHORT x, USHORT y);
- VOID set_image_pixel_color(struct Image *image, USHORT x, USHORT y,
- UBYTE color);
- BOOL create_avail_fonts(struct RenderInfo *ri);
- VOID free_avail_fonts(struct RenderInfo *ri);
-
- /* Static pragmas */
-
- #pragma regcall(calc_color_level(d0))
- #pragma regcall(init_render_info_images(a0))
- #pragma regcall(get_image_pixel_color(a0,d0,d1))
- #pragma regcall(set_image_pixel_color(a0,d0,d1,d2))
- #pragma regcall(create_avail_fonts(a0))
- #pragma regcall(free_avail_fonts(a0))
-
- /* Get render info for given screen */
-
- struct RenderInfo *
- get_render_info(struct Screen *screen, USHORT flags)
- {
- struct RenderInfo *ri;
-
- if (ri = AllocMem((LONG)sizeof(struct RenderInfo),
- (LONG)MEMF_PUBLIC | MEMF_CLEAR)) {
- struct Screen screen_data;
- USHORT screen_type;
-
- /* Get screen data - if no screen given then use workbench screen */
- if (!screen) {
- LONG ilock;
-
- /* Get pointer to workbench screen */
- ilock = LockIBase(0L);
- screen = IntuitionBase->FirstScreen;
- while (screen && (screen->Flags & SCREENTYPE) != WBENCHSCREEN) {
- screen = screen->NextScreen;
- }
- UnlockIBase(ilock);
- screen_type = WBENCHSCREEN;
- } else {
- screen_type = CUSTOMSCREEN;
- }
- if (GetScreenData((BYTE *)&screen_data, (LONG)sizeof(struct Screen),
- (LONG)screen_type, screen) == TRUE) {
- struct Image *image;
- USHORT *data;
- ULONG data_size;
- SHORT i;
-
- /* Get screen and window data */
- ri->ri_Screen = screen;
- screen = &screen_data;
- ri->ri_ScreenWidth = screen->Width;
- ri->ri_ScreenHeight = screen->Height;
- ri->ri_ScreenDepth = screen->RastPort.BitMap->Depth;
- ri->ri_WindowBorderTop = screen->BarHeight -
- screen->BarVBorder + screen->WBorTop;
- ri->ri_WindowBorderLeft = screen->WBorLeft;
- ri->ri_WindowBorderRight = screen->WBorRight;
- ri->ri_WindowBorderBottom = screen->WBorBottom;
- ri->ri_Flags = flags;
- ri->ri_ID = ISUP_ID;
-
- /* Calc chipmem buffer size for image data */
- for (i = 0, image = &images[0], data_size = 0;
- i < MAX_RENDER_IMAGES; i++, image++) {
- if (image->ImageData) {
- data_size += (image->Width / 16 + (image->Width & 15 ? 1 : 0))
- * image->Height * ri->ri_ScreenDepth * 2;
- }
- }
- if (data = AllocMem(data_size,
- (LONG)MEMF_PUBLIC | MEMF_CHIP | MEMF_CLEAR)) {
- SHORT num_colors;
-
- /* Insert image data buffer and size */
- ri->ri_ImageData = data;
- ri->ri_ImageDataSize = data_size;
-
- /* Calculate render colors */
- if ((num_colors = 1 << ri->ri_ScreenDepth) > MAX_RENDER_COLORS) {
- num_colors = MAX_RENDER_COLORS;
- }
- if (num_colors < 3) {
-
- /* Set render pens for monochrome screen */
- if (flags & RENDER_INFO_FLAG_BACK_FILL) {
- ri->ri_HighlightPen = 0;
- ri->ri_ShadowPen = 0;
- ri->ri_TextPen1 = 0;
- ri->ri_TextPen2 = 0;
- ri->ri_BackPen = 1;
- } else {
- ri->ri_HighlightPen = 1;
- ri->ri_ShadowPen = 1;
- ri->ri_TextPen1 = 1;
- ri->ri_TextPen2 = 1;
- ri->ri_BackPen = 0;
- }
- } else {
- struct ColorMap *cmap;
- SHORT back_color, max_diff, colors[MAX_RENDER_COLORS],
- color_levels[MAX_RENDER_COLORS],
- pens[MAX_RENDER_COLORS];
-
- /* Get current screen colors */
- Forbid();
- for (i = 0, cmap = screen->ViewPort.ColorMap; i < num_colors;
- i++) {
- colors[i] = GetRGB4(cmap, (LONG)i);
- color_levels[i] = calc_color_level(colors[i]);
- pens[i] = i;
- }
- Permit();
-
- /* Save normal background color */
- back_color = colors[0];
-
- /* Sort colors darkest to brightest (BUBBLE SORT) */
- for (i = 0; i < (num_colors - 1); i++) {
- SHORT j;
-
- for (j = i + 1; j < num_colors; j++) {
- if (color_levels[i] > color_levels[j]) {
- SHORT temp;
-
- /* Swap colors, color levels and pens */
- temp = colors[i];
- colors[i] = colors[j];
- colors[j] = temp;
-
- temp = color_levels[i];
- color_levels[i] = color_levels[j];
- color_levels[j] = temp;
-
- temp = pens[i];
- pens[i] = pens[j];
- pens[j] = temp;
- }
- }
- }
- if (flags & RENDER_INFO_FLAG_BACK_FILL) {
-
- /* Set render pens - highlight pen first */
- ri->ri_HighlightPen = pens[num_colors - 1]; /* use brightest color */
-
- /* Set shadow pen */
- ri->ri_ShadowPen = pens[0]; /* use darkest color */
-
- /* Set back pen */
- i = 1; /* use 2nd darkest color */
- if (! pens[i]) { /* don't use normal background color */
- i++;
- }
- ri->ri_BackPen = pens[i];
- back_color = colors[i]; /* new background color */
- } else {
-
- /* Set render pens - highlight pen first */
- i = num_colors - 1; /* use brightest color */
- if (! pens[i]) { /* don't use normal background color */
- i--;
- }
- ri->ri_HighlightPen = pens[i];
-
- /* Set shadow pen */
- i = 0; /* use darkest color */
- if (! pens[i]) { /* don't use normal background color */
- i++;
- }
- ri->ri_ShadowPen = pens[i];
-
- /* Set back pen */
- ri->ri_BackPen = 0;
- }
-
- /* Set text pen 1 - use color with greatest difference to
- * back color */
- for (i = 0, max_diff = 0; i < num_colors; i++) {
- SHORT diff;
-
- if ((diff = calc_color_difference(colors[i],
- back_color)) > max_diff) {
- max_diff = diff;
- ri->ri_TextPen1 = pens[i];
- }
- }
-
- /* Set text pen 2 - use color with greatest difference to
- * back color and other color than highlight or shadow pen */
- for (i = 0, max_diff = 0; i < num_colors; i++) {
- SHORT diff;
-
- if ((diff = calc_color_difference(colors[i],
- back_color)) > max_diff) {
- SHORT text1_pen = ri->ri_TextPen1, text2_pen = pens[i];
-
- /* Don't use text 1 pen again */
- if (text2_pen != text1_pen) {
-
- /* Use special algorithm for 1 and 2 bitplanes */
- if (num_colors < 5) {
-
- /* Try to get the pen not used for highlight and
- * shadow color if this isn't already used for
- * text 1 color */
- if ((text1_pen != ri->ri_HighlightPen &&
- text1_pen != ri->ri_ShadowPen) ||
- (text2_pen != ri->ri_HighlightPen &&
- text2_pen != ri->ri_ShadowPen)) {
- max_diff = diff;
- ri->ri_TextPen2 = pens[i];
- }
- } else {
-
- /* Try to get the best one from pens not used for
- * highlight and shadow color */
- if (text2_pen != ri->ri_HighlightPen &&
- text2_pen != ri->ri_ShadowPen) {
- max_diff = diff;
- ri->ri_TextPen2 = pens[i];
- }
- }
- }
- }
- }
- }
-
- /* Get font and attributes for rendering texts */
- if (!(flags & RENDER_INFO_FLAG_AVAIL_FONTS) ||
- create_avail_fonts(ri) == TRUE) {
- struct TextFont *tf;
-
- /* First try to open screen font - if any */
- Forbid();
- if (!screen->Font) {
- tf = NULL;
- } else {
- tf = open_font(ri, screen->Font);
- }
- Permit();
- if (tf) {
- struct TextAttr *ta = &ri->ri_TextAttr;
-
- /* Build text attribute structure from screen font */
- ta->ta_Name = (STRPTR)tf->tf_Message.mn_Node.ln_Name;
- ta->ta_YSize = tf->tf_YSize;
- ta->ta_Style = tf->tf_Style;
- ta->ta_Flags = tf->tf_Flags;
- } else {
-
- /* Fall back to TOPAZ80 */
- if (tf = open_font(ri, &topaz80_attr)) {
- CopyMem((BYTE *)&topaz80_attr, (BYTE *)&ri->ri_TextAttr,
- (LONG)sizeof(struct TextAttr));
- }
- }
- if (ri->ri_TextFont = tf) {
- init_render_info_images(ri);
- return(ri);
- }
- free_avail_fonts(ri);
- }
- }
- }
- FreeMem(ri, (LONG)sizeof(struct RenderInfo));
- }
- return(NULL);
- }
- /* Free render info */
-
- VOID
- free_render_info(struct RenderInfo *ri)
- {
- if (ri && ri->ri_ID == ISUP_ID) {
- if (ri->ri_TextFont) {
- CloseFont(ri->ri_TextFont);
- }
- free_avail_fonts(ri);
- FreeMem(ri->ri_ImageData, ri->ri_ImageDataSize);
- FreeMem(ri, (LONG)sizeof(struct RenderInfo));
- }
- }
- /* Calc color level with specified scaling values */
-
- STATIC SHORT
- calc_color_level(SHORT color)
- {
- return(calc_color_difference(color, 0));
- }
- /* Calc color difference with specified scaling values */
-
- SHORT /* non static - needed by menus.c too */
- calc_color_difference(SHORT color1, SHORT color2)
- {
- USHORT temp, diff;
-
- temp = (color1 & 0x00f) - (color2 & 0x00f);
- diff = temp * temp * BLUE_SCALE;
- temp = ((color1 >> 4) & 0x00f) - ((color2 >> 4) & 0x00f);
- diff += temp * temp * GREEN_SCALE;
- temp = ((color1 >> 8) & 0x00f) - ((color2 >> 8) & 0x00f);
- diff += temp * temp * RED_SCALE;
- return(diff);
- }
- /* Init render info images */
-
- STATIC VOID
- init_render_info_images(struct RenderInfo *ri)
- {
- struct Image *image_src = &images[0], *image_dest = &ri->ri_Images[0];
- USHORT i, *data = ri->ri_ImageData;
-
- CopyMem((BYTE *)image_src, (BYTE *)image_dest,
- (LONG)(MAX_RENDER_IMAGES * sizeof(struct Image)));
- for (i = 0; i < MAX_RENDER_IMAGES; i++, image_src++, image_dest++) {
-
- /* Set image depth first - needed by pixel functions */
- image_dest->Depth = ri->ri_ScreenDepth;
-
- /* Init image data if any */
- if (image_src->ImageData) {
- USHORT y, width = image_src->Width, height = image_src->Height,
- depth = image_dest->Depth; /* DEST image depth !!! */
-
- /* Set data buffer ptr */
- image_dest->ImageData = data;
- image_dest->PlanePick = (1 << depth) - 1;
- data += (width / 16 + (width & 15 ? 1 : 0)) * height * depth;
-
- /* Convert image data to current colors */
- for (y = 0; y < height; y++) {
- USHORT x;
-
- for (x = 0; x < width; x++) {
- UBYTE color;
-
- switch(get_image_pixel_color(image_src, x, y)) {
- case 0 : /* back pen */
- color = ri->ri_BackPen;
- break;
-
- case 1 : /* highlight pen */
- color = ri->ri_HighlightPen;
- break;
-
- case 2 : /* shadow pen */
- color = ri->ri_ShadowPen;
- break;
-
- default : /* special pen */
- color = ri->ri_TextPen2;
- break;
- }
- set_image_pixel_color(image_dest, x, y, color);
- }
- }
- } else {
- UBYTE color;
-
- /* No image data -> monochrome rectangle */
- switch(image_src->PlaneOnOff) {
- case 0 : /* back pen */
- color = ri->ri_BackPen;
- break;
-
- case 1 : /* highlight pen */
- color = ri->ri_HighlightPen;
- break;
-
- case 2 : /* shadow pen */
- color = ri->ri_ShadowPen;
- break;
-
- default : /* special pen */
- color = ri->ri_TextPen2;
- break;
- }
- image_dest->PlaneOnOff = color;
- }
- }
- }
- /* Get color of image pixel */
-
- STATIC UBYTE
- get_image_pixel_color(struct Image *image, USHORT x, USHORT y)
- {
- USHORT modulo = image->Width / 16 + (image->Width & 15 ? 1 : 0),
- *data = image->ImageData + y * modulo + x / 16,
- data_offset = image->Height * modulo,
- bit_mask = 0x8000 >> (x & 15);
- UBYTE i, depth = image->Depth, color_mask = 1, color = 0;
-
- for (i = 0; i < depth; i++, data += data_offset, color_mask <<= 1) {
- if (*data & bit_mask) {
- color |= color_mask;
- }
- }
- return(color);
- }
- /* Set color of image pixel */
-
- STATIC VOID
- set_image_pixel_color(struct Image *image, USHORT x, USHORT y, UBYTE color)
- {
- USHORT modulo = image->Width / 16 + (image->Width & 15 ? 1 : 0),
- *data = image->ImageData + y * modulo + x / 16,
- data_offset = image->Height * modulo,
- bit_mask = 0x8000 >> (x & 15);
- UBYTE i, depth = image->Depth;
-
- for (i = 0; i < depth; i++, data += data_offset, color >>= 1) {
- if (color & 1) {
- *data |= bit_mask;
- }
- }
- }
- /* Open window */
-
- struct Window *
- open_window(struct RenderInfo *ri, struct NewWindow *org_nw, USHORT flags)
- {
- struct Window *win = NULL;
-
- if (ri && ri->ri_ID == ISUP_ID && org_nw) {
- struct NewWindow new_nw = *org_nw, *nw = &new_nw;
- SHORT left_edge = nw->LeftEdge, top_edge = nw->TopEdge;
- USHORT width = nw->Width, height = nw->Height,
- max_width = ri->ri_ScreenWidth, max_height = ri->ri_ScreenHeight;
-
- /* Scale new window dimension */
- if (width > max_width) {
- width = max_width;
- left_edge = 0;
- } else {
- if ((left_edge + width) > max_width) {
- left_edge = max_width - width;
- }
- }
- if (height > max_height) {
- height = max_height;
- top_edge = 0;
- } else {
- if ((top_edge + height) > max_height) {
- top_edge = max_height - height;
- }
- }
-
- /* Change new window struct */
- if (flags & OPEN_WINDOW_FLAG_RENDER_PENS) {
-
- /* Set colors */
- if (ri->ri_Flags & RENDER_INFO_FLAG_BACK_FILL) {
- nw->DetailPen = ri->ri_TextPen1;
- nw->BlockPen = ri->ri_BackPen;
- } else {
- nw->DetailPen = ri->ri_BackPen;
- nw->BlockPen = ri->ri_TextPen1;
- }
- }
- if (!(flags & OPEN_WINDOW_FLAG_NO_INNER_WINDOW) &&
- (ri->ri_Flags & RENDER_INFO_FLAG_INNER_WINDOW)) {
- USHORT hoffset = ri->ri_WindowBorderLeft,
- voffset = ri->ri_WindowBorderTop;
-
- /* Change width and left edge for inner window dimension */
- if ((width += hoffset + ri->ri_WindowBorderRight) > max_width) {
- width = max_width;
- left_edge = 0;
- } else {
- if (left_edge > hoffset) {
- left_edge -= hoffset;
- if ((left_edge + width) > max_width) {
- left_edge = max_width - width;
- }
- } else {
- left_edge = 0;
- }
- }
-
- /* Change height and top edge for inner window dimension */
- if ((height += voffset + ri->ri_WindowBorderBottom) > max_height) {
- height = max_height;
- top_edge = 0;
- } else {
- if (top_edge > voffset) {
- top_edge -= voffset;
- if ((top_edge + height) > max_height) {
- top_edge = max_height - height;
- }
- } else {
- top_edge = 0;
- }
- }
- }
-
- /* Center window AFTER calculation of inner window dimension */
- if (flags & OPEN_WINDOW_FLAG_CENTER_SCREEN) {
-
- /* Center window on screen */
- left_edge = (max_width - width) / 2;
- top_edge = (max_height - height) / 2;
- } else {
- if (flags & OPEN_WINDOW_FLAG_CENTER_MOUSE) {
-
- /* Center window over current position of mouse pointer */
- left_edge = ri->ri_Screen->MouseX - width / 2;
- top_edge = ri->ri_Screen->MouseY - height / 2;
-
- /* Scale window position according to screen dimension */
- if (left_edge < 0) {
- left_edge = 0;
- } else {
- if (left_edge > (max_width - width)) {
- left_edge = max_width - width;
- }
- }
- if (top_edge < 0) {
- top_edge = 0;
- } else {
- if (top_edge > (max_height - height)) {
- top_edge = max_height - height;
- }
- }
- }
- }
-
- /* Insert position + dimension of window and try to open it */
- nw->LeftEdge = left_edge;
- nw->TopEdge = top_edge;
- nw->Width = width;
- nw->Height = height;
- if (win = OpenWindow(nw)) {
-
- /* Finally fill window background */
- if (ri->ri_Flags & RENDER_INFO_FLAG_BACK_FILL) {
- clear_window(ri, win, 0, 0, width, height, 0);
- }
- }
- }
- return(win);
- }
- /* Clear given rectangle of window with data from render info */
-
- VOID
- clear_window(struct RenderInfo *ri, struct Window *win, USHORT left_edge,
- USHORT top_edge, USHORT width, USHORT height, USHORT flags)
- {
- if (ri && ri->ri_ID == ISUP_ID && win) {
- USHORT inner_left, inner_top, inner_width, inner_height,
- ri_flags = ri->ri_Flags;
-
- /* Calc inner window dimension */
- if ((ri_flags & RENDER_INFO_FLAG_INNER_WINDOW) ||
- (ri_flags & RENDER_INFO_FLAG_BACK_FILL)) {
- inner_left = ri->ri_WindowBorderLeft;
- inner_top = ri->ri_WindowBorderTop;
- inner_width = win->Width - inner_left - ri->ri_WindowBorderRight;
- inner_height = win->Height - inner_top - ri->ri_WindowBorderBottom;
- } else {
- inner_left = 0;
- inner_top = 0;
- inner_width = win->Width;
- inner_height = win->Height;
- }
-
- /* Check if given rectangle fits into inner window */
- if ((SHORT)left_edge >= 0 && (SHORT)top_edge >= 0 && width &&
- height && left_edge < (inner_left + inner_width) &&
- top_edge < (inner_top + inner_height)) {
- struct RastPort *rp = win->RPort;
-
- /* Add offsets for inner window to given upper left position */
- if (!(flags & CLEAR_WINDOW_FLAG_ABSOLUTE_POS)) {
- left_edge += inner_left;
- top_edge += inner_top;
-
- /* Scale upper left position of given rectangle if neccessary */
- if (left_edge < inner_left) {
- left_edge = inner_left;
- }
- if (top_edge < inner_top) {
- top_edge = inner_top;
- }
- }
-
- /* Scale dimension of given rectangle if neccessary */
- if ((SHORT)width <= 0 || (left_edge + width) > (inner_left +
- inner_width)) {
- width = inner_left + inner_width - left_edge;
- }
- if ((SHORT)height <= 0 || (top_edge + height) > (inner_top +
- inner_height)) {
- height = inner_top + inner_height - top_edge;
- }
-
- /* Set draw mode, colors and fill pattern for using raster */
- if (flags & CLEAR_WINDOW_FLAG_USE_RASTER) {
- STATIC USHORT raster_pattern[] = { 0xaaaa, 0x5555 };
-
- SetDrMd(rp, (LONG)JAM2);
- SetAPen(rp, (LONG)ri->ri_HighlightPen);
- SetBPen(rp, (LONG)ri->ri_BackPen);
- SetAfPt(rp, &raster_pattern[0], 1L); /* macro !!! */
- } else {
-
- /* Set draw mode */
- if (!(flags & CLEAR_WINDOW_FLAG_CUSTOM_DRAW_MODE)) {
- SetDrMd(rp, (LONG)JAM1);
- }
-
- /* Set fill colors */
- if (!(flags & CLEAR_WINDOW_FLAG_CUSTOM_COLOR)) {
- USHORT apen;
-
- /* Check if special color needed */
- if (flags & CLEAR_WINDOW_FLAG_TEXT1_COLOR) {
- apen = ri->ri_TextPen1;
- } else {
- if (flags & CLEAR_WINDOW_FLAG_TEXT2_COLOR) {
- apen = ri->ri_TextPen2;
- } else {
-
- /* Use background color */
- if ((ri_flags & RENDER_INFO_FLAG_BACK_FILL) &&
- !(flags & CLEAR_WINDOW_FLAG_NORMAL_COLOR)) {
- apen = ri->ri_BackPen;
- } else {
- apen = 0;
- }
- }
- }
- SetAPen(rp, (LONG)apen);
- }
- }
-
- /* And do clearing window background */
- RectFill(rp, (LONG)left_edge, (LONG)top_edge, (LONG)(left_edge +
- width - 1), (LONG)(top_edge + height - 1));
-
- /* Clear fill pattern */
- if (flags & CLEAR_WINDOW_FLAG_USE_RASTER) {
- SetAfPt(rp, NULL, 1L); /* macro !!! */
- }
- }
- }
- }
- /* Close window safely, even if shared user port */
-
- VOID
- close_window(struct Window *win, BOOL more_windows)
- {
- if (win) {
-
- /* Check if any IDCMP flag used */
- if (win->UserPort) {
- struct IntuiMessage *msg, *succ;
-
- /* Reply all messages for given window */
- Forbid();
- msg = (struct IntuiMessage *)win->UserPort->mp_MsgList.lh_Head;
- while (succ = (struct IntuiMessage *)
- msg->ExecMessage.mn_Node.ln_Succ) {
- if (more_windows == FALSE || msg->IDCMPWindow == win) {
- Remove((struct Node *)msg);
- ReplyMsg((struct Message *)msg);
- }
- msg = succ;
- }
-
- /* Don't close shared user port */
- if (more_windows == TRUE) {
- win->UserPort = NULL;
- ModifyIDCMP(win, 0L);
- }
- Permit();
- }
- CloseWindow(win);
- }
- }
- /* Create list of available fonts - called by create_render_info() */
-
- STATIC BOOL
- create_avail_fonts(struct RenderInfo *ri)
- {
- struct AvailFontsHeader *afh;
- LONG size = DEFAULT_AVAIL_FONTS_BUFFER_SIZE;
- BOOL success = FALSE;
-
- /* Allocate buffer and fill it with data from available fonts */
- if (afh = AllocMem(size, (LONG)MEMF_PUBLIC)) {
- LONG new_size;
-
- if (new_size = AvailFonts((BYTE *)afh, size,
- (LONG)AFF_MEMORY | AFF_DISK)) {
- /* Allocate larger buffer and try again */
- FreeMem(afh, size);
- size += new_size;
- if (afh = AllocMem(size, (LONG)MEMF_PUBLIC)) {
- AvailFonts((BYTE *)afh, size, (LONG)AFF_MEMORY | AFF_DISK);
- }
- }
-
- /* Save font header in render info data structure */
- ri->ri_AvailFontsHeader = afh;
- ri->ri_AvailFontsHeaderSize = size;
- success = TRUE;
- }
- return(success);
- }
- /* Free list of available fonts - called by free_render_info() */
-
- STATIC VOID
- free_avail_fonts(struct RenderInfo *ri)
- {
- if (ri->ri_AvailFontsHeader && ri->ri_AvailFontsHeaderSize) {
- FreeMem(ri->ri_AvailFontsHeader, ri->ri_AvailFontsHeaderSize);
- }
- }
- /* Return ptr to list of available fonts */
-
- struct AvailFontsHeader *
- avail_fonts(struct RenderInfo *ri)
- {
- struct AvailFontsHeader *afh = NULL;
-
- if (ri && ri->ri_ID == ISUP_ID &&
- (ri->ri_Flags & RENDER_INFO_FLAG_AVAIL_FONTS)) {
- afh = ri->ri_AvailFontsHeader;
- }
- return(afh);
- }
- /* Check if given font is available and return its correct data */
-
- struct TextAttr *
- ask_font(struct RenderInfo *ri, struct TextAttr *ta)
- {
- struct TextAttr *best_ta = NULL;
-
- if (ri && ri->ri_ID == ISUP_ID && ta) {
- if (!(ri->ri_Flags & RENDER_INFO_FLAG_AVAIL_FONTS)) {
- best_ta = ta;
- } else {
- struct AvailFontsHeader *afh = ri->ri_AvailFontsHeader;
- USHORT num = afh->afh_NumEntries;
-
- if (num) {
- struct AvailFonts *af = (struct AvailFonts *)(afh + 1);
- USHORT search_ysize = ta->ta_YSize, best_ysize = 0;
-
- do {
- struct TextAttr *avail_ta = &af++->af_Attr;
- int stricmp(const char *_s1, const char *_s2); /* manually prototyping non ANSI function */
-
- if (!stricmp((BYTE *)avail_ta->ta_Name, (BYTE *)ta->ta_Name)) {
- USHORT avail_ysize = avail_ta->ta_YSize;
-
- if (avail_ysize == search_ysize) {
- best_ta = avail_ta;
- break;
- } else {
- if (avail_ysize < search_ysize) {
- if (avail_ysize > best_ysize) {
- best_ysize = avail_ysize;
- best_ta = avail_ta;
- }
- } else {
- if (!best_ysize || avail_ysize < best_ysize) {
- best_ysize = avail_ysize;
- best_ta = avail_ta;
- }
- }
- }
- }
- } while (--num);
- }
- }
- }
- return(best_ta);
- }
- /* Open best available text font */
-
- struct TextFont *
- open_font(struct RenderInfo *ri, struct TextAttr *ta)
- {
- struct TextFont *tf = NULL;
-
- if (ri && ri->ri_ID == ISUP_ID && ta) {
- if (ta = ask_font(ri, ta)) {
- if (!(tf = OpenFont(ta)) || tf->tf_YSize != ta->ta_YSize) {
- if (tf) {
- CloseFont(tf);
- }
- tf = OpenDiskFont(ta);
- }
- }
- }
- return(tf);
- }
-